package skiree.host.abetsy.api.service.global;

import cn.hutool.core.util.CharsetUtil;
import cn.hutool.core.util.XmlUtil;
import cn.hutool.http.HttpUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.vdurmont.emoji.EmojiParser;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.plugin.core.PluginRegistry;
import org.springframework.stereotype.Component;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import skiree.host.abetsy.api.annotation.EventQueue;
import skiree.host.abetsy.api.dao.CommentDao;
import skiree.host.abetsy.api.dao.EpisodeDao;
import skiree.host.abetsy.model.LocalComment;
import skiree.host.abetsy.model.LocalEpisode;
import skiree.host.abetsy.service.core.Stratege;

import javax.annotation.Resource;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Date;
import java.util.List;
import java.util.stream.Collectors;

@Component
public class GlobalDIYService {

    @Autowired
    private PluginRegistry<Stratege, LocalEpisode> registry;

    @Resource
    private EpisodeDao episodeDao;

    @Resource
    private CommentDao commentDao;

    @EventQueue()
    public void loadDanMu(LocalEpisode localEpisodeOld) {
        doEventInPool(localEpisodeOld);
    }

    public void doEventInPool(LocalEpisode localEpisodeOld) {
        // 先删除此剧集所有的子弹幕
        QueryWrapper<LocalComment> commentQuery = new QueryWrapper<>();
        commentQuery.eq("episode_id", localEpisodeOld.getId());
        commentDao.delete(commentQuery);
        // 然后加载
        localEpisodeOld.setStatus("init");
        episodeDao.updateById(localEpisodeOld);
        try {
            Stratege stratege = registry.getRequiredPluginFor(localEpisodeOld);
            stratege.loadDanMu(localEpisodeOld);
            localEpisodeOld.setStatus("loaded");
            localEpisodeOld.setTime(new Date());
            episodeDao.updateById(localEpisodeOld);
        } catch (Exception e) {
            try {
                LocalEpisode localEpisode = episodeDao.selectById(localEpisodeOld.getId());
                // 开始
                List<LocalComment> comments = new ArrayList<>();
                String xmlUrl = "https://fc.lyz05.cn/?url=" + localEpisode.getUrl();
                String resultXml = HttpUtil.get(xmlUrl, CharsetUtil.CHARSET_UTF_8);
                Document document = XmlUtil.parseXml(resultXml);
                NodeList nodeList = document.getElementsByTagName("d");
                for (int i = 0; i < nodeList.getLength(); i++) {
                    Node node = nodeList.item(i);
                    if (node.getNodeType() == Node.ELEMENT_NODE) {
                        Element element = (Element) node;
                        String content = element.getTextContent();
                        content = EmojiParser.removeAllEmojis(content);
                        if (!content.isEmpty()) {
                            double dataStrDou = Double.parseDouble(element.getAttribute("p").split(",")[0]);
                            BigDecimal start = new BigDecimal(dataStrDou).divide(new BigDecimal(1), 2, RoundingMode.HALF_UP);
                            if (start.longValue() >= 0) {
                                String time = start.toString();
                                String style = element.getAttribute("p").split(",")[3];
                                String position = "1";
                                String userId = "[bili]";
                                LocalComment localComment = new LocalComment();
                                localComment.setEpisodeId(localEpisode.getId());
                                localComment.setP(String.join(",", Arrays.asList(time, position, style, userId)));
                                localComment.setM(content);
                                localComment.setT(start);
                                comments.add(localComment);
                            }
                        }
                    }
                }
                // 时间相同的弹幕只保留三条
                comments = comments.stream()
                        .collect(Collectors.groupingBy(LocalComment::getT))
                        .values().stream()
                        .flatMap(list -> list.stream().limit(3))
                        .collect(Collectors.toList());
                commentDao.insert(comments);
            } catch (Exception exception) {
                localEpisodeOld.setStatus("error");
                localEpisodeOld.setTime(new Date());
                episodeDao.updateById(localEpisodeOld);
                throw new RuntimeException("DIY弹幕触底修复失败");
            }
        }
    }

}